package org.tangjl.utill.jacob;

import java.io.File;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;

/**
 * 通过jacob调用MSOffice接口转换Office文档为PDF文档
 * @author 唐家林
 * @time 2015年5月9日
 */
public class Office2PDF {
    private static final int xlTypePDF = 0;
    private static final int docTypePDF = 17;
    private static final int ppSaveAsPDF = 32;

	/**
	 * WORD转PDF
	 * @param inputFile WORD文件路径
	 * @param pdfFile 生成的PDF文件路径
	 * @return 转换成功返回true
	 */
	public boolean wordToPDF(String inputFile, String pdfFile) {
		long start = System.currentTimeMillis();
		ActiveXComponent app = null;
		Dispatch doc = null;
		try {
			File tofile = new File(pdfFile);
			if (tofile.exists()) { tofile.delete(); }

			log("打开文档..." + inputFile);
			app = new ActiveXComponent("Word.Application");
			app.setProperty("Visible", false);
			Dispatch docs = app.getProperty("Documents").toDispatch();
			doc = Dispatch.call(docs, "Open", inputFile, false, true).toDispatch();

			log("转换文档..." + inputFile + "...到..." + pdfFile);
			Dispatch.call(doc, "SaveAs", pdfFile, docTypePDF);
			long end = System.currentTimeMillis();
			log("转换完成..." + inputFile + "...用时：" + (end - start) + "ms.");
			return true;
		} catch (Exception e) {
			log("========Error:文档转换失败：" + pdfFile);
			e.printStackTrace();
			return false;
		} finally {
			Dispatch.call(doc, "Close", false);
	    	if (app != null) { app.invoke("Quit", 0); }
	    	ComThread.Release();
	    	log("释放资源..." + inputFile);
		}
	}

	/**
	 * EXCEL转PDF
	 * @param inputFile EXCEL文件路径
	 * @param pdfFile 生成的PDF文件路径
	 * @return 转换成功返回true
	 */
	public boolean excel2PDF(String inputFile, String pdfFile) {
		long start = System.currentTimeMillis();
		ActiveXComponent app = null;
		Dispatch workBook = null;
		try {
			File tofile = new File(pdfFile);
			if (tofile.exists()) { tofile.delete(); }

			log("打开文档..." + inputFile);
			app = new ActiveXComponent("Excel.Application");
			app.setProperty("Visible", false);
			Dispatch excels = app.getProperty("Workbooks").toDispatch();
			workBook = Dispatch.call(excels, "Open", inputFile, false, true).toDispatch();
			// 获取所有工作簿集合
			Dispatch sheets = Dispatch.get(workBook, "sheets").toDispatch();
			// 获取所有工作簿数量
			int count = Dispatch.get(sheets, "count").getInt();
			for (int i = count; i >= 1; i--) { // 变量每个工作薄,并设置每个打印页面的打印方向和缩放比例
				Dispatch sheet = Dispatch.invoke(sheets, "Item", Dispatch.Get,
						new Object[] { i }, new int[1]).toDispatch();
				Dispatch page = Dispatch.get(sheet, "PageSetup").toDispatch();

				Dispatch.put(page, "PrintArea", false); // 设置打印区域.false:打印整个工作表
				Dispatch.put(page, "Orientation", 1); // 打印方向,1:竖向打印,2:横向打印
				// 打印缩放,百分比
				// 10-400,false或10:百分之10,当且仅当Zoom为false,FitToPagesTall和FitToPagesWide才会生效
				Dispatch.put(page, "Zoom", false);
				Dispatch.put(page, "FitToPagesTall", false); // 设置是否将所有行调整为一页,false:否,1:是
				Dispatch.put(page, "FitToPagesWide", 1); // 设置是否将所有列调整为一页,false:否,1:是
			}
			log("转换文档..." + inputFile + "...到..." + pdfFile);
			Dispatch.call(workBook, "ExportAsFixedFormat", xlTypePDF, pdfFile);
			long end = System.currentTimeMillis();
			log("转换完成..." + inputFile + "...用时：" + (end - start) + "ms.");
			return true;
		} catch (Exception e) {
			log("========Error:文档转换失败：" + inputFile);
			e.printStackTrace();
			return false;
		} finally {
			Dispatch.call(workBook, "Close", false);
			if (app != null) { app.invoke("Quit"); }
			ComThread.Release();
			log("释放资源..." + inputFile);
		}
	}

	/**
	 * PPT转PDF
	 * @param inputFile PPT文件路径
	 * @param pdfFile 生成的PDF文件路径
	 * @return 转换成功返回true
	 */
	public boolean ppt2PDF(String inputFile, String pdfFile) {
		long start = System.currentTimeMillis();
		try {
			File tofile = new File(pdfFile);
			if (tofile.exists()) { tofile.delete(); }

			log("打开文档..." + inputFile);
			ActiveXComponent app = new ActiveXComponent("PowerPoint.Application");
			Dispatch ppts = app.getProperty("Presentations").toDispatch();
			Dispatch ppt = Dispatch.call(ppts, "Open", inputFile, true, true, false).toDispatch();

			log("转换文档..." + inputFile + "...到..." + pdfFile);
			Dispatch.call(ppt, "SaveAs", pdfFile, ppSaveAsPDF);
			long end = System.currentTimeMillis();
			log("转换完成..." + inputFile + "...用时：" + (end - start) + "ms.");
			return true;
		} catch (Exception e) {
			log("========Error:文档转换失败：" + pdfFile);
			e.printStackTrace();
			return false;
		} finally {
			// 不需要使用命令关闭和退出,因为PPT是单进程,无论打开多少分PPT文件都只有一个进程
			// 在多线程多文档同时转换的情况下,未转换完毕所有文档是无法关闭和退出的,所以会抛出异常
			// 在最后只需要通过ComThread.Release();释放资源就行了,因为它会在所有文档转换完毕的情况下释放
			// Dispatch.call(ppt, "Close");
			// if (app != null) { app.invoke("Quit"); }

			// 等待释放资源,在多线程情况下,因为PPT转换是单进程
			// 所有如果有多分文件在同时转换,所有文件转换完毕后才会释放资源并退出该函数,否则在此会挂起
			ComThread.Release();
			log("释放资源..." + inputFile);
		}
	}

	public static void log (String msg) {
		System.out.print(msg + "\r\n");
	}
    public static void main(String[] args) {
    	final String file = "C:\\designTemplates.xlsx";
    	Office2PDF d = new Office2PDF();
//		d.wordToPDF(file, file + ".pdf");
    	d.excel2PDF(file, file + ".pdf");
//		d.ppt2PDF(file, file + ".pdf");
//        for (int i = 1; i < 100; i++) {
//        	final int index = i;
//	        new Thread(new Runnable() {
//				@Override
//				public void run() {
//					Office2PDF d = new Office2PDF();
//					String pdfPath = file + "_" + Thread.currentThread().getName() + "_" + index + ".pdf";
//					d.wordToPDF(file, pdfPath);
//					d.excel2PDF(file, pdfPath);
//					d.ppt2PDF(file, pdfPath);
//				}
//			}).start();
//        }
    }
}
